// interface T1 {
//     a: number;
//     b: string;
// }

// interface T2 {
//     c: number;
//     d: string;
// }

// interface T3 extends T1, T2 {
//     e: string
// }

// // 相比于继承而言, 继承可以有自己的类型, 而交叉没有
// let t3: T3 = {
//     a: 1,
//     b: 'zs',
//     c: 1,
//     d: 'zs',
//     e: ''
// }

// interface FilterAttrs {
//     name: string;
//     age: string;
//     weight: string;
// }

// // 泛型工具类型
// interface DatabaseInfo {
//     id: string
// }
// type DataSource = 'user' | 'detail' | 'list'
// const x: Record<DataSource, DatabaseInfo> = {
//     user: {
//         id: '1'
//     },
//     detail: {
//         id: '2'
//     },
//     list: {
//         id: '3'
//     }
// }

// interface Person {
//     name: string;
//     age: number;
//     weight: string;
//     height: string;
// }
// type pick = Pick<Person, 'height' | 'age'>
// type omit = Omit<Person, 'age'>

// type Person1 = keyof Person
// type exclude = Exclude<Person1, 'name'>

// let a: unknown = 123
// a = ''
// a = undefined
// a = null

// class Walkable {
//     legs: number
// }
// class Eatable {
//     tooth: number;
// }
// type With = Walkable & Eatable
// let b: With = {
//     legs: 123,
//     tooth: 123
// }

// class
// class Animal {
//     constructor(name: string) {
//         this.name = name
//     }
//     get name() {
//         return '名字'
//     }
//     set name(value: string) {
//         console.log('setter: ' + value);
//     }
// }

// let p1 = new Animal('zs')
// console.log(p1.name);
// p1.name = 'ls'
// console.log(p1.name);

// 修饰符
// class Animal {
//     public name;
//     private age;
//     protected sex;
//     public constructor(name: string, age: number, sex: string) {
//         this.name = name
//         this.age = age
//         this.sex = sex
//     }
// }
// let p1 = new Animal('zs', 18, '男')
// console.log(p1.name);
// // console.log(p1.age);
// // console.log(p1.sex);

// class Animal1 extends Animal {
//     constructor(name: string, age: number, sex: string) {
//         super(name, age, sex)
//         console.log(this.name, this.sex);
//         // age只能被父类访问
//     }
// }
// let p2 = new Animal1('ls', 20, '男')

// class Animal3 {
//     public name;
//     constructor(name: string) {
//         this.name = name
//     }
// }
// console.log(new Animal3('animal3').name) // animal3

// class Animal2 {
//     constructor(public name: string) { } // 简洁形式
// }
// console.log(new Animal2('animal2').name) // animal2

// 抽象类
// 抽象类是行为的抽象，一般来封装公共属性的方法的，不能被实例化
// abstract class CommonAnimal {
//     name: string
//     abstract speak(): void
// }

// // 静态类
// class Animal5 {
//     static age: number = 18;
// }
// console.log(Animal5.age);

// 交叉类型
// interface IPerson {
//     id: string;
//     name: string;
// }

// interface IWorker {
//     age: number;
// }
// type IStaff = IPerson & IWorker
// const staff: IStaff = {
//     name: '',
//     age: 0,
//     id: ''
// }

// enum Weather {
//     SPRING, SUMMER, AUTUMN, WINTER
// }
// type w = keyof typeof Weather

// interface Person2 {
//     readonly id: number
//     [propName: string]: any //任意属性
// }
// let p2: Person2 = {
//     id: 123,
//     name: 'zs'
// }

// class Monkey {
//     constructor(public climb: string) {}
// }
// class Personp {
//     constructor(public sports: string) {}
// }
// function getAnimalName(animal: Monkey | Personp) {
//     if (animal instanceof Monkey) {
//         console.log(animal.climb)
//     } else {
//         console.log(animal.sports)
//     }
// }
// let pp = new Monkey('climb')
// getAnimalName(pp)

// 从函数类型的参数中使用的类型构造元组类型
// 该方法是为了创建元组类型
// let f1: (arg: { a: number; b: string }) => void
// type par = Parameters<typeof f1>
// type par1 = Parameters<(first: string) => void>
// type par2 = Parameters<<T>(arg: T[], length: number) => T[]>
// type par3 = Parameters<any>

// let pp1: par = [{a: 1, b: ''}]
// let pp2: par3 = [1, undefined, null]
// let pp3: par2 = [[], 1]

// function reverse1(arg: number): number
// function reverse1(arg: string): string
// function reverse1(arg: string | number): string | number {
//     if (typeof arg === 'number') {
//         return Number(arg.toString().split('').reverse().join(''));
//     } else if (typeof arg === 'string') {
//         return arg.split('').reverse().join('');
//     }
// }

// class Da {
//     constructor(private _age: number) { }
//     get age() {
//         return this._age
//     }
//     set age(age: number) {
//         this._age = age
//     }
// }

// const dada = new Da(12)
// dada.age = 13
// console.log(dada.age);

// class Data {
//     public _name: string;
//     constructor(name) {
//         this._name = name
//     }

//     set name(val: string) {
//         this._name = val
//     }

//     get name() {
//         return this._name
//     }
// }

// interface testInter {
//     name: string;
//     age: number;
// }

// // 对象
// function showKey<K extends keyof T, T>(items: K[], obj: T): T[K][] {
//     return items.map(item => obj[item])
// }
// showKey<keyof testInter, testInter>(['name', 'age'], { name: 'ls', age: 18 })
// function getKey<K extends keyof T, T>(keyItem: K, obj: T): T[K] {
//     return obj[keyItem]
// }
// console.log(getKey<keyof testInter, Partial<testInter>>('name', { name: 'zs' }));

// // 数组
// function getArrKey<K extends keyof T, T>(key: K, obj: T): K {
//     return key
// }
// console.log(getArrKey<number, Array<number>>(1, [1]));

interface Person {
    name: string;
    age: number;
    sex: string;
}
// class Teacher {
//     constructor(private info: Person) {}
//     getInfo(key: keyof Person) {
//         return this.info[key]
//     }
// }
// 写法等同
class Teacher {
    constructor(private info: Person) {}
    getInfo<T extends keyof Person>(key: T): Person[T] {
        return this.info[key];
    }
}
let p = new Teacher({
    name: 'zs',
    age: 18,
    sex: '1',
});
console.log(p.getInfo('name'));

interface UserInfo {
    name: string;
    age: number;
    sex?: string;
    [key: string]: any;
}
const myInfo: UserInfo = {
    name: 'zs',
    age: 18,
    sex: '男',
    weight: '56',
};
console.log(myInfo);

// 数字索引接口
interface numberIndex {
    [x: number]: string;
}
// 相当于声明了一个字符串类型的数组
let chars: numberIndex = ['A', 'B'];
let chars1: numberIndex = {
    1: 'zs',
};

interface stringIndex {
    [x: string]: string;
}
let strIdx: stringIndex = {
    name: 'name',
};

// interface stringIndex {
//     [x: string]: string
//     [z: number]: number // error
// }

// interface stringIndex {
//     [x: string]: any
//     [z: number]: number // error
// }

export {};
